package com.h3bpm.starcharge.service.impl.k3c;

import com.alibaba.fastjson.parser.Feature;
import com.h3bpm.starcharge.bean.k3c.CustomerInfo.Linkman;
import com.h3bpm.starcharge.bean.k3c.CustomerInfo.BankInfo;

import OThinker.H3.Entity.DataModel.BizObject;
import OThinker.H3.Entity.Instance.Data.InstanceData;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.gson.Gson;
import com.h3bpm.starcharge.bean.k3c.CustomerInfo;
import com.h3bpm.starcharge.bean.k3c.CustomerView;
import com.h3bpm.starcharge.bean.k3c.LastNumber;
import com.h3bpm.starcharge.common.bean.*;
import com.h3bpm.starcharge.common.uitl.FileUtil;
import com.h3bpm.starcharge.common.uitl.MapUtil;
import com.h3bpm.starcharge.common.uitl.OkHttpUtil;
import com.h3bpm.starcharge.common.uitl.k3c.K3cUtil;
import com.h3bpm.starcharge.config.K3CloundConfig;
import com.h3bpm.starcharge.ret.k3c.K3cBase;
import com.h3bpm.starcharge.service.k3c.BaseDataService;
import com.h3bpm.starcharge.service.k3c.CustomerService;
import com.h3bpm.starcharge.service.k3c.K3cService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * K3C客户接口
 *
 * @author LLongAgo
 * @date 2019/4/9
 * @since 1.0.0
 */
@Service
public class CustomerServiceImpl implements CustomerService {

    @Autowired
    private K3cUtil util;
    @Autowired
    private K3cService k3cService;
    @Autowired
    private K3CloundConfig k3CloundConfig;
    @Autowired
    private BaseDataService baseDataService;

    @Value("${k3c_dbId}")
    private String dbId;
    @Value("${k3c_uid}")
    private String uid;
    @Value("${k3c_pwd}")
    private String pwd;
    @Value("${k3c_lang}")
    private int lang;
    @Value("${golangApiUrl}")
    private String golangApiUrl;

    private static final String STAR_CHARGE = "星充";
    private static final String GUO_CHUANG = "国创";
    private static final String FORM_ID = "BD_Customer";
    private static final String CONTACT_FORM_ID = "BD_CommonContact";

    /**
     * 保存
     * @param instanceData  InstanceData
     * @return RetResult
     */
    @Override
    public RetResult save(InstanceData instanceData) throws Exception {
        HashMap<String, Object> valueTable = instanceData.getBizObject().getValueTable();
        JSONObject basic = setSaveParam(valueTable);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("formid", FORM_ID);
        jsonObject.put("data", basic);
        System.out.println(basic.toJSONString());
        // 禁止循环引用
        String param = JSON.toJSONString(jsonObject, SerializerFeature.DisableCircularReferenceDetect);
        String cookie = util.getLoginCookie();
        // 保存
        RetResult result = k3cService.save(k3CloundConfig.getUrl() + k3CloundConfig.getSave(), cookie, param);
        if (!RestfulErrorCode.SUCCESS.getCode().equals(result.getCode())) {
            return result;
        }
        K3cBase k3cBase = (K3cBase) result.getData();
        String submitParam = k3cService.buildParam(FORM_ID, k3cBase.getId(), null, null);
        // 提交
        RetResult save = k3cService.save(k3CloundConfig.getUrl() + k3CloundConfig.getSubmit(), cookie, submitParam);
        if (!RestfulErrorCode.SUCCESS.getCode().equals(save.getCode())) {
            return save;
        }
        // 审核
        RetResult save1 = k3cService.save(k3CloundConfig.getUrl() + k3CloundConfig.getAudit(), cookie, submitParam);
        if (!RestfulErrorCode.SUCCESS.getCode().equals(save1.getCode())) {
            return save1;
        }
        // 根据使用组织分配
        String useOrganization = (String) valueTable.get("useOrganization");
        JsonResult<List<BaseResult>> organizationList;
        StringBuilder sb = new StringBuilder();
        if (useOrganization.equals(GUO_CHUANG)) {
            organizationList = baseDataService.getOrganizationBySql("FNUMBER like '104%'");
        } else if (useOrganization.equals(STAR_CHARGE)) {
            organizationList = baseDataService.getOrganizationBySql("FNUMBER like '102%'");
        } else {
            organizationList = baseDataService.getOrganizationBySql("FNUMBER = 101");
        }
        List<BaseResult> data = organizationList.getData();
        for (BaseResult d : data) {
            sb.append(d.getValue()).append(",");
        }
        String orgStr = sb.toString();
        orgStr = orgStr.substring(0, orgStr.length() - 1);
        // 拼接分配参数
        String allocateParam = k3cService.buildAllocateParam(FORM_ID, orgStr, k3cBase.getId());
        RetResult save2 = k3cService.save(k3CloundConfig.getUrl() + k3CloundConfig.getAllocate(), cookie, allocateParam);
        if (!RestfulErrorCode.SUCCESS.getCode().equals(save2.getCode())) {
            return save2;
        }
        // 保存联系人
        BizObject[] bizObjects = (BizObject[]) valueTable.get("linkman");
        if (null != bizObjects && bizObjects.length > 0) {
            RetResult retResult = saveContact(bizObjects, cookie);
            K3cBase base = (K3cBase) retResult.getData();
            String ids = base.getId();
            String number = ((K3cBase) result.getData()).getId();
            Map<String, String> map = new HashMap<>(4);
            map.put("ids", ids);
            map.put("number", number);
            OkHttpUtil.post(golangApiUrl + "contact/contactBindCustomer", map);
        }
        return result;
    }

    /**
     * 客户修改
     * @param instanceData  InstanceData
     * @return  RetResult
     * @throws Exception
     */
    @Override
    public RetResult edit(InstanceData instanceData) throws Exception {
        HashMap<String, Object> valueTable = instanceData.getBizObject().getValueTable();
        JSONObject basic = setEditParam(valueTable);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("formid", FORM_ID);
        jsonObject.put("data", basic);
        // 禁止循环引用
        String param = JSON.toJSONString(jsonObject, SerializerFeature.DisableCircularReferenceDetect);
        String cookie = util.getLoginCookie();
        // 反审核
        String unAuditParam = k3cService.buildParam(FORM_ID, (String) valueTable.get("customerId"), null, null);
        RetResult unAuditResult = k3cService.save(k3CloundConfig.getUrl() + k3CloundConfig.getUnAudit(), cookie, unAuditParam);
        if (!unAuditResult.getCode().equals(RestfulErrorCode.SUCCESS.getCode())) {
            return unAuditResult;
        }
        // 保存
        RetResult result = k3cService.save(k3CloundConfig.getUrl() + k3CloundConfig.getSave(), cookie, param);
        if (!RestfulErrorCode.SUCCESS.getCode().equals(result.getCode())) {
            return result;
        }
        K3cBase k3cBase = (K3cBase) result.getData();
        String submitParam = k3cService.buildParam(FORM_ID, k3cBase.getId(), null, null);
        // 提交
        k3cService.save(k3CloundConfig.getUrl() + k3CloundConfig.getSubmit(), cookie, submitParam);
        // 审核
        k3cService.save(k3CloundConfig.getUrl() + k3CloundConfig.getAudit(), cookie, submitParam);

        // 修改联系人
        BizObject[] bizObjects = (BizObject[]) valueTable.get("linkmanEdit");
        if (bizObjects.length > 0) {
            editContact(bizObjects, cookie, ((K3cBase) result.getData()).getId());
        }

        return result;
    }

    private void setParam(JSONObject model, HashMap<String, Object> valueTable) throws Exception {
        if (null != valueTable.get("customerId")) {
            model.put("FCUSTID", valueTable.get("customerId"));
        }
        // 保存--获取最新的编码
        String customerCode = (String) valueTable.get("customerCode");
        if ("".equals(customerCode.trim())) {
            Map<String, String> postMap = new HashMap<>(2);
            postMap.put("group", (String) valueTable.get("customerGroupId"));
            String json = OkHttpUtil.post(golangApiUrl + "customer/lastNumber", postMap);
            LastNumber lastNumber = new Gson().fromJson(json, LastNumber.class);
            valueTable.put("customerCode", lastNumber.getData().getFnumber());
        }
        model.put("FNumber", valueTable.get("customerCode"));
        model.put("FName", valueTable.get("customerName"));
        // 国家
        Map<String, Object> country = new HashMap<>(4);
        country.put("FNumber", valueTable.get("country"));
        model.put("FCOUNTRY", country);
        String[] keys = {"FINVOICETITLE", "FTAXREGISTERCODE", "FINVOICEBANKNAME", "FINVOICETEL", "FINVOICEBANKACCOUNT", "FINVOICEADDRESS", "FADDRESS"};
        String[] values = {"FPTT", "NSDJH", "KHYH", "KPLXDH", "YHZH", "KPTXDZ", "address"};
        MapUtil.batchSet(model, valueTable, keys, values);
        // 客户分组
        Map<String, Object> group = new HashMap<>(4);
        group.put("FNumber", valueTable.get("customerGroupId"));
        model.put("FGroup", group);
        // 结算币别
        Map<String, Object> currency = new HashMap<>(4);
        currency.put("FNumber", valueTable.get("currency"));
        model.put("FTRADINGCURRID", currency);
        // 结算方式
        Map<String, Object> clearType = new HashMap<>(4);
        clearType.put("FNumber", valueTable.get("clearType"));
        model.put("FSETTLETYPEID", clearType);
        // 收款条件
        Map<String, Object> collection = new HashMap<>(4);
        collection.put("FNumber", valueTable.get("collection"));
        model.put("FRECCONDITIONID", collection);
        model.put("FInvoiceType", valueTable.get("invoiceType"));
        // 税分类
        Map<String, Object> taxType = new HashMap<>(4);
        taxType.put("FNumber", valueTable.get("taxType"));
        model.put("FTaxType", taxType);
        // 默认税率
        Map<String, Object> defaultTax = new HashMap<>(4);
        defaultTax.put("FNumber", valueTable.get("defaultTax"));
        model.put("FTaxRate", defaultTax);
        // 客户关联类型
        Map<String, Object> cognateType = new HashMap<>(4);
        cognateType.put("FNumber", valueTable.get("cognateType"));
        model.put("F_WB_KHGLLX", cognateType);
        // 客户类别
        if (null != valueTable.get("cstomerType")) {
            Map<String, Object> cstomerType = new HashMap<>(4);
            cstomerType.put("FNumber", valueTable.get("cstomerType"));
            model.put("FCustTypeId", cstomerType);
        }
        // 省市
        Map<String, Object> customerext = new LinkedHashMap<>(8);
        customerext.put("FEnableSL", false);
        Map<String, Object> province = new HashMap<>(4);
        province.put("FNumber", valueTable.get("province"));
        customerext.put("FPROVINCE", province);
        Map<String, Object> city = new HashMap<>(4);
        city.put("FNumber", valueTable.get("city"));
        customerext.put("FCITY", city);
        model.put("FT_BD_CUSTOMEREXT", customerext);
        // 银行信息
        List<Map<String, Object>> banks = new ArrayList<>();
        BizObject[] zbBizObjects = (BizObject[]) valueTable.get("bankInfo");
        if (null == zbBizObjects) {
            zbBizObjects = (BizObject[]) valueTable.get("bankInfoEdit");
        }
        if (null != zbBizObjects && zbBizObjects.length > 0) {
            for (BizObject object : zbBizObjects) {
                HashMap<String, Object> table = object.getValueTable();
                Map<String, Object> bank = new HashMap<>(8);
                if (null != table.get("bankId")) {
                    bank.put("FENTRYID", table.get("bankId"));
                }
                String[] key = {"FOPENBANKNAME", "FBANKCODE", "FACCOUNTNAME", "FOpenAddressRec"};
                String[] value = {"bank", "account", "accountName", "address"};
                MapUtil.batchSet(bank, table, key, value);
                Map<String, Object> bCurrency = new HashMap<>(4);
                bCurrency.put("FNumber", valueTable.get("currency"));
                bank.put("FCURRENCYID", bCurrency);
                bank.put("FISDEFAULT1", false);
                banks.add(bank);
            }
            model.put("FT_BD_CUSTBANK", banks);
        } else {
            model.put("FT_BD_CUSTBANK", banks);
        }
    }

    private JSONObject setEditParam(HashMap<String, Object> valueTable) throws Exception {
        // 解析json模板
        String template = FileUtil.readJsonData("k3c/customer-edit.json");
        JSONObject basic = JSON.parseObject(template, Feature.OrderedField);
        JSONObject model = basic.getJSONObject("Model");
        // 设置公共参数
        setParam(model, valueTable);
        // 联系人
        BizObject[] bizObjects = (BizObject[]) valueTable.get("linkman");
        if (null != bizObjects && bizObjects.length > 0) {
            // 修改联系人
        }
        return basic;
    }

    private JSONObject setSaveParam(HashMap<String, Object> valueTable) throws Exception {
        // 解析json模板
        String template = FileUtil.readJsonData("k3c/customer-save.json");
        JSONObject basic = JSON.parseObject(template, Feature.OrderedField);
        JSONObject model = basic.getJSONObject("Model");
        // 设置公共参数
        setParam(model, valueTable);
        return basic;
    }

    /**
     * 客户详情
     * @param number    编码
     * @return  RetResult
     * @throws Exception
     */
    @Override
    public RetResult info(String number) throws Exception {
        String result = util.view(FORM_ID, String.format("{\"CreateOrgId\":0,\"Number\":\"%s\",\"Id\":\"\"}", number));
        CustomerView customerView = new Gson().fromJson(result, CustomerView.class);
        if (null != customerView.getResult().getResponseStatus()) {
            return RetResponse.makeErrRsp("该客户不存在!");
        }
        CustomerView.ResultBeanX.ResultBean resultBean = customerView.getResult().getResult();
        CustomerInfo customerInfo = new CustomerInfo();
        customerInfo.setId(String.valueOf(resultBean.getId()));
        customerInfo.setCustomerName(resultBean.getName().get(0).getValue());
        customerInfo.setCustomerGroup(resultBean.getFGroup().getName().get(0).getValue());
        customerInfo.setCognateType(resultBean.getF_WB_KHGLLX().getFNumber());
        customerInfo.setCustomerCode(resultBean.getNumber());
        customerInfo.setCountry(resultBean.getCOUNTRY().getFNumber());
        customerInfo.setProvince(null != resultBean.getBD_CUSTOMEREXT().get(0).getPROVINCE() ? resultBean.getBD_CUSTOMEREXT().get(0).getPROVINCE().getFNumber() : "");
        customerInfo.setCity(null != resultBean.getBD_CUSTOMEREXT().get(0).getCITY() ? resultBean.getBD_CUSTOMEREXT().get(0).getCITY().getFNumber() : "");
        customerInfo.setAddress(resultBean.getADDRESS());
        customerInfo.setCurrency(resultBean.getTRADINGCURRID().getNumber());
        customerInfo.setClearType(null != resultBean.getSETTLETYPEID() ? resultBean.getSETTLETYPEID().getNumber() : "");
        customerInfo.setCollection(null != resultBean.getRECCONDITIONID() ? resultBean.getRECCONDITIONID().getNumber() : "");
        customerInfo.setTaxType(null != resultBean.getTaxType() ? resultBean.getTaxType().getFNumber() : "");
        customerInfo.setInvoiceType(resultBean.getInvoiceType());
        customerInfo.setDefaultTax(null != resultBean.getTaxRate() ? resultBean.getTaxRate().getNumber() : "");
        customerInfo.setFPTT(resultBean.getINVOICETITLE());
        customerInfo.setNSDJH(resultBean.getFTAXREGISTERCODE());
        customerInfo.setKHYH(resultBean.getINVOICEBANKNAME());
        customerInfo.setYHZH(resultBean.getINVOICEBANKACCOUNT());
        customerInfo.setKPTXDZ(resultBean.getINVOICEADDRESS());
        customerInfo.setKPLXDH(resultBean.getINVOICETEL());
        customerInfo.setCustomerGroupId(resultBean.getFGroup().getNumber());
        customerInfo.setLinkman(new ArrayList<Linkman>());
        ArrayList<BankInfo> bankInfos = new ArrayList<>();
        List<CustomerView.ResultBeanX.ResultBean.BDCUSTBANKBean> custbank = resultBean.getBD_CUSTBANK();
        if (null != custbank && custbank.size() > 0) {
            for (CustomerView.ResultBeanX.ResultBean.BDCUSTBANKBean bank : custbank) {
                if (bank.getId() > 0) {
                    BankInfo bankInfo = new BankInfo();
                    bankInfo.setId(String.valueOf(bank.getId()));
                    bankInfo.setBank(bank.getOPENBANKNAME().get(0).getValue());
                    bankInfo.setAccount(bank.getBANKCODE());
                    bankInfo.setAccountName(bank.getACCOUNTNAME());
                    bankInfo.setAddress(bank.getOpenAddressRec());
                    bankInfo.setCurrency(null != bank.getCURRENCYID() ? bank.getCURRENCYID().getNumber() : "");
                    bankInfos.add(bankInfo);
                }
            }
        }
        customerInfo.setBankInfo(bankInfos);
        return RetResponse.makeOKRsp(customerInfo);
    }

    /**
     * 保存联系人
     * @param zbBizObjects  BizObject[]
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    private RetResult saveContact(BizObject[] zbBizObjects, String cookie) throws Exception {
        // 解析json模板
        String template = FileUtil.readJsonData("k3c/contact-save-batch.json");
        JSONObject basic = JSON.parseObject(template);
        // 获取model数组
        JSONArray jsonArray = basic.getJSONArray("Model");
        Map<String, Object> modelTemplate = (Map<String, Object>) jsonArray.get(0);
        jsonArray.clear();
        for (BizObject zbBizObject : zbBizObjects) {
            setContactParam(modelTemplate, zbBizObject, jsonArray);
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("formid", CONTACT_FORM_ID);
        jsonObject.put("data", basic);
        // 禁止循环引用
        String param = JSON.toJSONString(jsonObject, SerializerFeature.DisableCircularReferenceDetect);
        // 保存
        return k3cService.save(k3CloundConfig.getUrl() + k3CloundConfig.getBatchSave(), cookie, param);
    }

    private void setContactParam(Map<String, Object> modelTemplate, BizObject zbBizObject, JSONArray jsonArray) throws Exception {
        Map<String, Object> newModel = new HashMap<>(32);
        newModel.putAll(modelTemplate);
        Map<String, Object> zbValueTable = zbBizObject.getValueTable();
        String[] keys = {"FNAME", "FMOBILE", "FCOMPANYTYPE"};
        String[] values = {"linkName", "mobile", "type"};
        MapUtil.batchSet(newModel, zbValueTable, keys, values);
        jsonArray.add(newModel);
    }

    /**
     * 修改联系人
     * @param zbBizObjects  BizObject[]
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    private void editContact(BizObject[] zbBizObjects, String cookie, String number) throws Exception {
        // 解析json模板
        String template = FileUtil.readJsonData("k3c/contact-save-batch.json");
        JSONObject basic = JSON.parseObject(template);
        // 获取model数组
        JSONArray jsonArray = basic.getJSONArray("Model");
        Map<String, Object> modelTemplate = (Map<String, Object>) jsonArray.get(0);
        jsonArray.clear();
        for (BizObject zbBizObject : zbBizObjects) {
            Map<String, String> model = new HashMap<>(8);
            Map<String, Object> valueTable = zbBizObject.getValueTable();
            String id = (String) valueTable.get("linkmanId");
            if (!"0".equals(id)) {
                model.put("id", id);
                model.put("name", (String) valueTable.get("linkName"));
                model.put("mobile", (String) valueTable.get("mobile"));
                // 直接数据库更新
                OkHttpUtil.post(golangApiUrl + "contact/updateContact", model);
            } else {
                // 新增联系人
                setContactParam(modelTemplate, zbBizObject, jsonArray);
            }
        }
        if (jsonArray.size() > 0) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("formid", CONTACT_FORM_ID);
            jsonObject.put("data", basic);
            // 禁止循环引用
            String param = JSON.toJSONString(jsonObject, SerializerFeature.DisableCircularReferenceDetect);
            // 保存
            RetResult retResult = k3cService.save(k3CloundConfig.getUrl() + k3CloundConfig.getBatchSave(), cookie, param);
            K3cBase base = (K3cBase) retResult.getData();
            String ids = base.getId();
            Map<String, String> map = new HashMap<>(4);
            map.put("ids", ids);
            map.put("number", number);
            OkHttpUtil.post(golangApiUrl + "contact/contactBindCustomer", map);
        }
    }
}